﻿using System;
using System.Runtime.Serialization;

namespace DependencyAnalysis.DataModel
{
    public enum MemberType
    {
        Field,
        Method,
        TypeReference
    }

    [Serializable]
    [DataContract(IsReference = true)]
    [KnownType(typeof(TypeDescriptor))]
    [KnownType(typeof(MemberType))]
    [KnownType(typeof(NodeVisibility))]
    [KnownType(typeof(Purity))]
    public class MemberDescriptor : IDescriptor
    {
        private string _identifier;

        [DataMember(Order = 1)]
        public string Identifier
        {
            get { return _identifier; }
            set
            {
                _identifier = value;
                ComparableIdentifier = ("" + _identifier).ToLowerInvariant();
            }
        }

        [DataMember(Order = 2)]
        public string FullName { get; set; }

        [DataMember(Order = 3)]
        public string Name { get; set; }

        public string Signature
        {
            get
            {
                var fullName = FullName;
                if (fullName == null)
                {
                    return string.Empty;
                }
                var nameSeparator = fullName.IndexOf("§");
                return FullName.Substring(nameSeparator + 1);
            }
        }

        public IDescriptor Parent
        {
            get { return ImplementingType; }
        }

        [DataMember(Order = 4)]
        public TypeDescriptor ImplementingType { get; set; }

        [DataMember(Order = 5)]
        public NodeVisibility Visibility { get; set; }

        [DataMember(Order = 6)]
        public bool IsDefinedByInterface { get; set; }

        [DataMember(Order = 7)]
        public bool IsOverride { get; set; }

        [DataMember(Order = 8)]
        public bool IsGenerated { get; set; }

        [DataMember(Order = 9)]
        public bool IsStatic { get; set; }

        [DataMember(Order = 10)]
        public int ParameterCount { get; set; }

        [DataMember(Order = 11)]
        public int VariableCount { get; set; }

        [DataMember(Order = 12)]
        public MemberType MemberType { get; set; }

        private Purity _purity = Purity.Undefined;

        [DataMember(Order = 13)]
        public Purity Purity
        {
            get { return _purity; }
            set { _purity = value; }
        }

        [DataMember(Order = 14)]
        public bool IsAbstract { get; set; }

        [DataMember(Order = 15)]
        public TypeDescriptor ReturningType { get; set; }

        public bool IsPure
        {
            get { return MemberType == MemberType.Method && Purity == Purity.Pure; }
        }

        public override bool Equals(object obj)
        {
            if (!(obj is MemberDescriptor))
            {
                return false;
            }

            return string.Equals(ComparableIdentifier, ((MemberDescriptor)obj).ComparableIdentifier);
        }

        internal string ComparableIdentifier { get; set; }

        public override int GetHashCode()
        {
            return ("" + ComparableIdentifier).GetHashCode();
        }

        public override string ToString()
        {
            return GetType().Name + ": " + FullName;
        }
    }
}
